home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / ka9q_src.arc / FTPCLI.C < prev    next >
C/C++ Source or Header  |  1988-11-29  |  14KB  |  643 lines

  1. /* FTP client (interactive user) code */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "mbuf.h"
  5. #include "netuser.h"
  6. #include "icmp.h"
  7. #include "timer.h"
  8. #include "tcp.h"
  9. #include "iface.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include "ftp.h"
  13. #include "session.h"
  14. #include "cmdparse.h"
  15.  
  16. extern struct session *current;
  17. extern char nospace[];
  18. extern char badhost[];
  19. static char notsess[] = "Not an FTP session!\n";
  20. static char cantwrite[] = "Can't write %s\n";
  21. static char cantread[] = "Can't read %s\n";
  22.  
  23. int donothing(),doftpcd(),dolist(),doget(),dols(),dopass(),dopass2(),doput(),
  24.     dotype(),doabort(),domkdir(),dormdir();
  25.  
  26. struct cmds ftpabort[] = {
  27.     "abort",     doabort, 0, NULLCHAR, NULLCHAR,
  28.     NULLCHAR,    NULLFP,  0, "Only valid command is \"abort\"", NULLCHAR,
  29. };
  30.  
  31. struct cmds ftpcmds[] = {
  32.     "",        donothing,    0,    NULLCHAR,        NULLCHAR,
  33.     "cd",        doftpcd,    2,    "cd <directory>",    NULLCHAR,
  34.     "dir",        dolist,        0,    NULLCHAR,        NULLCHAR,
  35.     "list",        dolist,        0,    NULLCHAR,        NULLCHAR,
  36.     "get",        doget,        2,    "get remotefile <localfile>",    NULLCHAR,
  37.     "ls",        dols,        0,    NULLCHAR,        NULLCHAR,
  38.     "mkdir",    domkdir,    2,    "mkdir <directory>",    NULLCHAR,
  39.     "nlst",        dols,        0,    NULLCHAR,        NULLCHAR,
  40.     "rmdir",    dormdir,    2,    "rmdir <directory>",    NULLCHAR,
  41.     "pass",        dopass,        1,    "pass [<password>]",    NULLCHAR,
  42.     "put",        doput,        2,    "put localfile <remotefile>",    NULLCHAR,
  43.     "type",        dotype,        0,    NULLCHAR,        NULLCHAR,
  44.     NULLCHAR,    NULLFP,        0,     NULLCHAR,        NULLCHAR,
  45. };
  46.  
  47. /* Handle top-level FTP command */
  48. doftp(argc,argv)
  49. int argc;
  50. char *argv[];
  51. {
  52.     int32 resolve();
  53.     int ftpparse();
  54.     char *inet_ntoa();
  55.     void ftpccr(),ftpccs();
  56.     struct session *s;
  57.     struct ftp *ftp,*ftp_create();
  58.     struct tcb *tcb;
  59.     struct socket lsocket,fsocket;
  60.  
  61.     lsocket.address = ip_addr;
  62.     lsocket.port = lport++;
  63.     if((fsocket.address = resolve(argv[1])) == 0){
  64.         printf(badhost,argv[1]);
  65.         return 1;
  66.     }
  67.     if(argc < 3)
  68.         fsocket.port = FTP_PORT;
  69.     else
  70.         fsocket.port = atoi(argv[2]);
  71.  
  72.     /* Allocate a session control block */
  73.     if((s = newsession()) == NULLSESSION){
  74.         printf("Too many sessions\n");
  75.         return 1;
  76.     }
  77.     current = s;
  78.     if((s->name = malloc((unsigned)strlen(argv[1])+1)) != NULLCHAR)
  79.         strcpy(s->name,argv[1]);
  80.     s->type = FTP;
  81.     s->parse = ftpparse;
  82.  
  83.     /* Allocate an FTP control block */
  84.     if((ftp = ftp_create(0)) == NULLFTP){
  85.         s->type = FREE;
  86.         printf(nospace);
  87.         return 1;
  88.     }
  89.     ftp->state = COMMAND_STATE;
  90.     s->cb.ftp = ftp;    /* Downward link */
  91.     ftp->session = s;    /* Upward link */
  92.  
  93.     /* Now open the control connection */
  94.     tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,
  95.         0,ftpccr,NULLVFP,ftpccs,0,(char *)ftp);
  96.     ftp->control = tcb;
  97.     go();
  98.     return 0;
  99. }
  100. /* Parse user FTP commands */
  101. int
  102. ftpparse(line,len)
  103. char *line;
  104. int16 len;
  105. {
  106.     struct mbuf *bp;
  107.  
  108.     if(current->cb.ftp->state == PASSCMD_STATE) {
  109.         (void)dopass2(line, len) ;
  110.         return ;
  111.     }
  112.  
  113.     if(current->cb.ftp->state != COMMAND_STATE){
  114.         /* The only command allowed in data transfer state is ABORT */
  115.         if(cmdparse(ftpabort,line) == -1){
  116.             printf("Transfer in progress; only ABORT is acceptable\n");
  117.         }
  118.         fflush(stdout);
  119.         return;
  120.     }
  121.  
  122.     /* Save it now because cmdparse modifies the original */
  123.     bp = qdata(line,len);
  124.  
  125.     if(cmdparse(ftpcmds,line) == -1){
  126.         /* Send it direct */
  127.         if(bp != NULLBUF)
  128.             send_tcp(current->cb.ftp->control,bp);
  129.         else
  130.             printf(nospace);
  131.     } else {
  132.         free_p(bp);
  133.     }
  134.     fflush(stdout);
  135. }
  136. /* Handle null line to avoid trapping on first command in table */
  137. static
  138. int
  139. donothing(argc,argv)
  140. int argc;
  141. char *argv[];
  142. {
  143. }
  144. /* Translate 'cd' to 'cwd' for convenience */
  145. static
  146. int
  147. doftpcd(argc,argv)
  148. int argc;
  149. char *argv[];
  150. {
  151.     register struct ftp *ftp;
  152.  
  153.     ftp = current->cb.ftp;
  154.     return sndftpmsg(ftp,"CWD %s\r\n",argv[1]);
  155. }
  156. /* Translate 'mkdir' to 'xmkd' for convenience */
  157. static
  158. int
  159. domkdir(argc,argv)
  160. int argc;
  161. char *argv[];
  162. {
  163.     register struct ftp *ftp;
  164.  
  165.     ftp = current->cb.ftp;
  166.     return sndftpmsg(ftp,"XMKD %s\r\n",argv[1]);
  167. }
  168. /* Translate 'rmdir' to 'xrmd' for convenience */
  169. static
  170. int
  171. dormdir(argc,argv)
  172. int argc;
  173. char *argv[];
  174. {
  175.     register struct ftp *ftp;
  176.  
  177.     ftp = current->cb.ftp;
  178.     return sndftpmsg(ftp,"XRMD %s\r\n",argv[1]);
  179. }
  180. /* Handle "type" command from user */
  181. static
  182. int
  183. dotype(argc,argv)
  184. int argc;
  185. char *argv[];
  186. {
  187.     register struct ftp *ftp;
  188.  
  189.     ftp = current->cb.ftp;
  190.     if(argc < 2){
  191.         switch(ftp->type){
  192.         case IMAGE_TYPE:
  193.             printf("Image\n");
  194.             break;
  195.         case ASCII_TYPE:
  196.             printf("Ascii\n");
  197.             break;
  198.         }
  199.         return 0;
  200.     }
  201.     switch(*argv[1]){
  202.     case 'i':
  203.     case 'b':
  204.         ftp->type = IMAGE_TYPE;
  205.         sndftpmsg(ftp,"TYPE I\r\n");
  206.         break;
  207.     case 'a':
  208.         ftp->type = ASCII_TYPE;
  209.         sndftpmsg(ftp,"TYPE A\r\n");
  210.         break;
  211.     case 'l':
  212.         ftp->type = IMAGE_TYPE;
  213.         sndftpmsg(ftp,"TYPE L %s\r\n",argv[2]);
  214.         break;
  215.     default:
  216.         printf("Invalid type %s\n",argv[1]);
  217.         return 1;
  218.     }
  219.     return 0;
  220. }
  221. /* Start receive transfer. Syntax: get <remote name> [<local name>] */
  222. static
  223. doget(argc,argv)
  224. int argc;
  225. char *argv[];
  226. {
  227.     void ftpdr(),ftpcds();
  228.     char *remotename,*localname;
  229.     register struct ftp *ftp;
  230.     char *mode;
  231.  
  232.     ftp = current->cb.ftp;
  233.     if(ftp == NULLFTP){
  234.         printf(notsess);
  235.         return 1;
  236.     }
  237.     remotename = argv[1];
  238.     if(argc < 3)
  239.         localname = remotename;
  240.     else
  241.         localname = argv[2];
  242.  
  243.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  244.         fclose(ftp->fp);
  245.     ftp->fp = NULLFILE;
  246.  
  247.     if(ftp->type == IMAGE_TYPE)
  248.         mode = binmode[WRITE_BINARY];
  249.     else
  250.         mode = "w";
  251.  
  252.     if((ftp->fp = fopen(localname,mode)) == NULLFILE){
  253.         printf(cantwrite,localname);
  254.         return 1;
  255.     }
  256.     ftp->state = RECEIVING_STATE;
  257.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  258.  
  259.     /* Generate the command to start the transfer */
  260.     return sndftpmsg(ftp,"RETR %s\r\n",remotename);
  261. }
  262. /* List remote directory. Syntax: dir <remote directory/file> [<local name>] */
  263. static
  264. dolist(argc,argv)
  265. int argc;
  266. char *argv[];
  267. {
  268.     void ftpdr(),ftpcds();
  269.     register struct ftp *ftp;
  270.  
  271.     ftp = current->cb.ftp;
  272.     if(ftp == NULLFTP){
  273.         printf(notsess);
  274.         return 1;
  275.     }
  276.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  277.         fclose(ftp->fp);
  278.     ftp->fp = NULLFILE;
  279.  
  280.     if(argc < 3){
  281.         ftp->fp = stdout;
  282.     } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
  283.         printf(cantwrite,argv[2]);
  284.         return 1;
  285.     }
  286.     ftp->state = RECEIVING_STATE;
  287.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  288.     /* Generate the command to start the transfer
  289.      * It's done this way to avoid confusing the 4.2 FTP server
  290.      * if there's no argument
  291.      */
  292.     if(argc > 1)
  293.         return sndftpmsg(ftp,"LIST %s\r\n",argv[1]);
  294.     else
  295.         return sndftpmsg(ftp,"LIST\r\n","");
  296. }
  297. /* Abbreviated (name only) list of remote directory.
  298.  * Syntax: ls <remote directory/file> [<local name>]
  299.  */
  300. static
  301. dols(argc,argv)
  302. int argc;
  303. char *argv[];
  304. {
  305.     void ftpdr(),ftpcds();
  306.     register struct ftp *ftp;
  307.  
  308.     ftp = current->cb.ftp;
  309.     if(ftp == NULLFTP){
  310.         printf(notsess);
  311.         return 1;
  312.     }
  313.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  314.         fclose(ftp->fp);
  315.     ftp->fp = NULLFILE;
  316.  
  317.     if(argc < 3){
  318.         ftp->fp = stdout;
  319.     } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
  320.         printf(cantwrite,argv[2]);
  321.         return 1;
  322.     }
  323.     ftp->state = RECEIVING_STATE;
  324.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  325.     /* Generate the command to start the transfer */
  326.     if(argc > 1)
  327.         return sndftpmsg(ftp,"NLST %s\r\n",argv[1]);
  328.     else
  329.         return sndftpmsg(ftp,"NLST\r\n","");
  330. }
  331. /* Handle user "pass" command.  Allow Blanking of password */
  332. static
  333. int
  334. dopass(argc,argv)
  335. int argc;
  336. char *argv[];
  337. {
  338.     register struct ftp *ftp;
  339.  
  340.     ftp = current->cb.ftp;
  341.     if (argc > 1) /* Password printed in the clear - send it now */
  342.         return sndftpmsg(ftp,"PASS %s\r\n",argv[1]);
  343.     else {
  344.         ftp->state = PASSCMD_STATE ;
  345.         current->noecho = 1 ;
  346.         noecho() ;
  347.         printf("Enter user password: ") ;
  348.         fflush(stdout) ;
  349.     }
  350.     return 0;
  351. }
  352. /* Handle second half of user "pass" command: Blanked Password */
  353. static
  354. int
  355. dopass2(line,len)
  356. char *line;
  357. int16 len;
  358. {
  359.     register struct ftp *ftp;
  360.  
  361.     ftp = current->cb.ftp;
  362.     ftp->state = COMMAND_STATE ;
  363.     current->noecho = 0 ;
  364.     echo() ;
  365.  
  366.     /* Have unechoed password - send it */
  367.     line[len-1] = '\0' ;
  368.     return sndftpmsg(ftp,"PASS %s\r\n",line);
  369. }
  370. /* S